use std::time::{SystemTime, UNIX_EPOCH};
use dashmap::DashMap;
use tokio::time::{interval, Duration};
use std::sync::Arc;

/// TTL manager for handling key expiration
#[derive(Debug)]
pub struct TTLManager {
    /// Map of key to expiration timestamp
    expiry_map: Arc<DashMap<String, u64>>,
}

impl TTLManager {
    /// Create a new TTL manager
    pub fn new() -> Self {
        Self {
            expiry_map: Arc::new(DashMap::new()),
        }
    }

    /// Get current timestamp in seconds
    pub fn current_timestamp() -> u64 {
        SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs()
    }

    /// Set expiration for a key
    pub fn set_expiry(&self, key: String, ttl_seconds: u64) {
        let expiry = Self::current_timestamp() + ttl_seconds;
        self.expiry_map.insert(key, expiry);
    }

    /// Check if a key has expired
    pub fn is_expired(&self, key: &str) -> bool {
        if let Some(expiry) = self.expiry_map.get(key) {
            *expiry < Self::current_timestamp()
        } else {
            false
        }
    }

    /// Get TTL for a key
    pub fn get_ttl(&self, key: &str) -> Option<i64> {
        if let Some(expiry) = self.expiry_map.get(key) {
            let now = Self::current_timestamp();
            if *expiry > now {
                Some((*expiry - now) as i64)
            } else {
                Some(-2) // Expired
            }
        } else {
            Some(-1) // No expiration
        }
    }

    /// Remove expiration for a key
    pub fn remove_expiry(&self, key: &str) -> bool {
        self.expiry_map.remove(key).is_some()
    }

    /// Get all expired keys
    pub fn get_expired_keys(&self) -> Vec<String> {
        let now = Self::current_timestamp();
        let mut expired = Vec::new();

        for entry in self.expiry_map.iter() {
            if *entry.value() < now {
                expired.push(entry.key().clone());
            }
        }

        expired
    }

    /// Remove expired entries
    pub fn cleanup_expired(&self) -> usize {
        let expired_keys = self.get_expired_keys();
        let count = expired_keys.len();

        for key in expired_keys {
            self.expiry_map.remove(&key);
        }

        count
    }

    /// Start background cleanup task
    pub fn start_cleanup_task(self: Arc<Self>) -> tokio::task::JoinHandle<()> {
        tokio::spawn(async move {
            let mut interval = interval(Duration::from_secs(60)); // Run every minute

            loop {
                interval.tick().await;
                let cleaned = self.cleanup_expired();
                if cleaned > 0 {
                    tracing::debug!("Cleaned up {} expired keys", cleaned);
                }
            }
        })
    }
}